# 自动化生成MD5
import json, os, hashlib, requests
import logging
import random
import re
import time
import traceback
from tqdm import tqdm
import pyperclip as cb
import yaml

headers = {'Content-Type': 'application/json', 'User-Agent': 'PostmanRuntime/7.26.8'}
logging.basicConfig(filename='log.txt', level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s')
remoteFilePath = "/home/yss/data/ysstech/"
ipAddress = "http://localhost:12333"
jindutiao_total = 100
jindutiaoStep = 0.5
sleepSecond = 0.2
autoUpgrade = False

def readConfig():
    config = {}
    try:
        with open('config.yaml', 'r', encoding='utf-8') as f:
            config = yaml.load(f.read(), Loader=yaml.FullLoader)  # 其返回一个字典数据
            log("读取配置完成：" + str(config))
    except Exception as e:
        logging.error(traceback.format_exc())
    return config

# 获取微服务升级参数
def serviceConfig(md5Json):
    serviceCode = []
    if len(json.loads(md5Json)) >= 0:
        for item in json.loads(md5Json):
            serviceCode.append(item["serviceKey"])

    serciceParamRow = {
        "id": 0,
        "serviceKey": "",
        "port": 0,
        "minRam": 0,
        "maxRam": 0,
        "startParam": "",
        "version": ""
    }
    response = requests.get(f"{ipAddress}/microservice/info")
    responseJson = json.loads(response.text)
    if responseJson.get("code") == "200":
        resultParam = []
        # print("请求成功: " + str(responseJson.get("data")))
        for service in responseJson.get("data"):
            if item["serviceKey"] not in serviceCode:
                continue
            for item in json.loads(md5Json):
                if item["serviceKey"] == service["serviceKey"]:
                    serciceParamRow['id'] = service['serviceId']
                    serciceParamRow['serviceKey'] = service['serviceKey']
                    serciceParamRow['port'] = service['servicePort']
                    serciceParamRow['minRam'] = service['serviceMinRam']
                    serciceParamRow['maxRam'] = service['serviceMaxRam']
                    serciceParamRow['startParam'] = service['serviceStartParam']
                    serciceParamRow["version"] = item['versionNum']
                    resultParam.append(serciceParamRow)

        reqParam = {"microserviceInfos": resultParam, "sqlPath": None}
        log("开始升级：" + str(md5Json))
        response = requests.post(ipAddress + "/publish/upgrade", json.dumps(reqParam), headers=headers)
        if (json.loads(response.text).get("code") == "200"):
            log(str(serviceCode) + "升级" + json.loads(response.text).get("msg"))
            time.sleep(1.5)

# 获取jar配置目录
def getJarPath(configFilePath):
    # 获取jar 配置路径
    f = open(configFilePath, 'r', encoding='utf-8')
    path = str(f.read().strip())
    logging.debug("jar 配置路径：" + path)
    return path


# 读取文件 获取json
def getJson(path):
    if len(path) >= 0:
        m = '['
        file_name_list = os.listdir(path)
        for i in file_name_list:
            # 文件名以.jar结尾才处理 否则跳过
            if not i.endswith('.jar'):
                continue
            need_path = path + '\\' + i
            with open(need_path, 'rb') as (f):
                content = f.read()
                md5 = hashlib.md5(content).hexdigest()
            serviceKey = i.replace('.jar', '').split('-V')[0]
            versionNum = 'V' + i.replace('.jar', '').split('-V')[1]
            jj = {
                'serviceKey': serviceKey,
                'versionNum': versionNum,
                'md5': md5
            }
            jj = str(jj) + ',\n'
            m = m + jj
        else:
            m = m.strip()[:-1]
            m = m + ']'
            return m.replace("'", '"')


def writeJson(str):
    file_test = open((os.getcwd() + '/' + 'md5.json'), 'w', encoding='utf-8')
    file_test.write(str)
    file_test.close()


# 初始化版本
def initJar(mf5Json):
    response = requests.post(ipAddress + "/init/version/release", mf5Json, headers=headers)
    return json.loads(response.text).get("code") == "200"


def uploadIsOver(batchId, overMaxTime=100):
    response = requests.get(
        ipAddress + "/file/transfer/log?operatorType=UPLOAD_UPDATE_JAR&batchId=" + str(batchId))
    responseJson = json.loads(response.text)

    statusList = []
    for item in responseJson.get("data"):
        statusList.append(item["status"])
    statusList = list(set(statusList))
    if len(statusList) == 1 and statusList[0] == 1:
        log("文件上传完成, 耗时：" + str(100 - overMaxTime))
        time.sleep(1)
        return True
    elif overMaxTime <= 0:
        return False
    else:
        time.sleep(5)
        overMaxTime -= 5;
        return uploadIsOver(batchId, overMaxTime)

def uploadIsOverV2(batchId, overMaxTime=100):
    # jar包总数
    num = jarNum(batchId)
    # 进度条
    with tqdm(total = 100) as pbar:
        pbar.set_description('开始上传jar包>>>:')
        sucPreNum = 0
        totalJindu = jindutiao_total
        while sucPreNum < num and overMaxTime >= 0:
            # 成功数
            sucPreNum = jarSuccNum(batchId)
            overMaxTime -= sleepSecond
            # 进行进度更新
            pbar.update(jindutiaoStep)
            totalJindu -= jindutiaoStep
        pbar.update(totalJindu)


def jarNum(batchId):
    response = requests.get(
        ipAddress + "/file/transfer/log?operatorType=UPLOAD_UPDATE_JAR&batchId=" + str(batchId))
    responseJson = json.loads(response.text)
    return len(responseJson.get("data"))

def jarSuccNum(batchId):
    time.sleep(sleepSecond)
    response = requests.get(
        ipAddress + "/file/transfer/log?operatorType=UPLOAD_UPDATE_JAR&batchId=" + str(batchId))
    responseJson = json.loads(response.text)
    succ = []
    for item in responseJson.get("data"):
        if item["status"] == 1:
            succ.append(item["status"])
    return len(succ)

# 上传jar
def uploadJar(path):
    batchId = random.randint(1686042429427, 9999999999999)
    reqJson = {
        "batchId": batchId,
        "localFilePath": path,
        "remoteFilePath": remoteFilePath
    }
    uploadRep = requests.post(ipAddress + "/jarfile/upload/auto", json.dumps(reqJson), headers=headers)
    if (json.loads(uploadRep.text).get("code") == "200"):
        uploadIsOverV2(batchId)
        # return uploadIsOver(batchId)
    return True

# 记录日志
def log(logInfo):
    logging.info(logInfo)
    print(logInfo)

try:
    # ############### 开始 #################
    config = readConfig()
    if bool(config):
        if config != None:
            ipAddress = config.get("ipAddress")
            autoUpgrade = config.get("autoUpgrade")
            autoInit = config.get("autoInit")
            remoteFilePath = config.get("remoteFilePath")
            jindutiaoStep = config.get("jindutiao_step")
            sleepSecond = config.get("sleepSecond")
    path = cb.paste()
    log("从剪切板中读取jar包配置路径：" + str(path))
    md5Json = getJson(path)
    writeJson(md5Json)
    # 复制到剪切板
    cb.copy(md5Json)
    log("md5已复制到剪切板中")
    log("md5Json：" + md5Json)
    if autoUpgrade:
        initResult = initJar(getJson(path))
        if (initResult):
            if uploadJar(path):
                serviceConfig(md5Json)
    # ############### 结束 #################

except Exception as e:
    logging.error(traceback.format_exc())
